package com.ssy.lingxi.after.sale.serviceimpl;

import cn.hutool.core.date.DateUtil;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.ssy.lingxi.after.sale.entity.*;
import com.ssy.lingxi.after.sale.model.constant.AfterSaleTypeEnum;
import com.ssy.lingxi.after.sale.model.dto.OperateLogInputDto;
import com.ssy.lingxi.after.sale.model.dto.OperateLogOuterResponDto;
import com.ssy.lingxi.after.sale.model.vo.request.WorkflowPageVO;
import com.ssy.lingxi.after.sale.model.vo.response.RepairOuterWorkflowRecordVO;
import com.ssy.lingxi.after.sale.model.vo.response.ReplaceOuterWorkflowRecordVO;
import com.ssy.lingxi.after.sale.model.vo.response.ReturnOuterWorkflowRecordVO;
import com.ssy.lingxi.after.sale.repository.OuterWorkflowRecordRepository;
import com.ssy.lingxi.after.sale.service.IOuterWorkflowRecordService;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.Wrapper;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * 外部工作流记录接口服务实现
 * @author 伍将
 * @date 2020/9/3
 * @version 2.0.0
 */
@Service
public class OuterWorkflowRecordServiceImpl implements IOuterWorkflowRecordService {

    @Resource
    private OuterWorkflowRecordRepository outerRecordRepository;
    @Resource
    private JPAQueryFactory jpaQueryFactory;
    /**
     * 获取维修外部工作流记录
     * @author 伍将
     * @date 2020/12/11
     * @param dataId:
     * @return 维修外部工作流记录
     **/
    @Override
    public Wrapper<List<RepairOuterWorkflowRecordVO>> getRepairRecordList(Long dataId) {
        AtomicReference<Integer> step = new AtomicReference<>(1);
        List<RepairOuterWorkflowRecordVO> resultList = outerRecordRepository.findByAfterSaleIdAndAfterSaleTypeOrderByOperateTimeAsc(dataId, AfterSaleTypeEnum.REPAIR.getCode())
                .stream().map(r -> {
                    RepairOuterWorkflowRecordVO queryVO = new RepairOuterWorkflowRecordVO();
                    queryVO.setStep(step.get());
                    step.getAndSet(step.get() + 1);
                    queryVO.setRoleName(r.getRoleName());
                    queryVO.setStatus(r.getStatus());
                    queryVO.setStatusCode(r.getStatusCode());
                    queryVO.setOperate(r.getOperate());
                    queryVO.setOperateTime(DateUtil.format(DateUtil.date(r.getOperateTime()), "yyyy-MM-dd HH:mm"));
                    queryVO.setOpinion(r.getOpinion());

                    return queryVO;
                }).collect(Collectors.toList());

        return Wrapper.success(resultList);
    }

    /**
     * 获取换货外部工作流记录
     * @author 伍将
     * @date 2020/12/11
     * @param dataId:
     * @return 换货外部工作流记录
     **/
    @Override
    public Wrapper<List<ReplaceOuterWorkflowRecordVO>> getReplaceRecordList(Long dataId) {
        AtomicReference<Integer> step = new AtomicReference<>(1);
        List<ReplaceOuterWorkflowRecordVO> resultList = outerRecordRepository.findByAfterSaleIdAndAfterSaleTypeOrderByOperateTimeAsc(dataId, AfterSaleTypeEnum.REPLACE.getCode())
                .stream().map(r -> {
                    ReplaceOuterWorkflowRecordVO queryVO = new ReplaceOuterWorkflowRecordVO();
                    queryVO.setStep(step.get());
                    step.getAndSet(step.get() + 1);
                    queryVO.setRoleName(r.getRoleName());
                    queryVO.setStatus(r.getStatus());
                    queryVO.setStatusCode(r.getStatusCode());
                    queryVO.setOperate(r.getOperate());
                    queryVO.setOperateTime(DateUtil.format(DateUtil.date(r.getOperateTime()), "yyyy-MM-dd HH:mm"));
                    queryVO.setOpinion(r.getOpinion());

                    return queryVO;
                }).collect(Collectors.toList());

        return Wrapper.success(resultList);
    }

    /**
     * 获取退货外部工作流记录
     * @author 伍将
     * @date 2020/12/11
     * @param dataId:
     * @return 退货外部工作流记录
     **/
    @Override
    public Wrapper<List<ReturnOuterWorkflowRecordVO>> getReturnRecordList(Long dataId) {
        AtomicReference<Integer> step = new AtomicReference<>(1);
        List<ReturnOuterWorkflowRecordVO> resultList = outerRecordRepository.findByAfterSaleIdAndAfterSaleTypeOrderByOperateTimeAsc(dataId, AfterSaleTypeEnum.RETURN.getCode())
                .stream().map(r -> {
                    ReturnOuterWorkflowRecordVO queryVO = new ReturnOuterWorkflowRecordVO();
                    queryVO.setStep(step.get());
                    step.getAndSet(step.get() + 1);
                    queryVO.setRoleName(r.getRoleName());
                    queryVO.setStatus(r.getStatus());
                    queryVO.setStatusCode(r.getStatusCode());
                    queryVO.setOperate(r.getOperate());
                    queryVO.setOperateTime(DateUtil.format(DateUtil.date(r.getOperateTime()), "yyyy-MM-dd HH:mm"));
                    queryVO.setOpinion(r.getOpinion());

                    return queryVO;
                }).collect(Collectors.toList());

        return Wrapper.success(resultList);
    }

    /**
     * 分页查询维修外部工作流
     * @author 伍将
     * @date 2020/12/11
     * @param user:
     * @param pageVO:
     * @return 维修外部工作流
     **/
    @Override
    public Wrapper<PageData<RepairOuterWorkflowRecordVO>> pageRepairRecord(UserLoginCacheDTO user, WorkflowPageVO pageVO) {
        Page<OuterWorkflowRecordDO> result = pageRecord(pageVO, AfterSaleTypeEnum.REPAIR.getCode());
        AtomicReference<Integer> step = new AtomicReference<>((pageVO.getCurrent() - 1) * pageVO.getPageSize() + 1);
        List<RepairOuterWorkflowRecordVO> resultList = result.getContent().stream().map(r -> {
            RepairOuterWorkflowRecordVO queryVO = new RepairOuterWorkflowRecordVO();
            queryVO.setStep(step.get());
            step.getAndSet(step.get() + 1);
            queryVO.setRoleName(r.getRoleName());
            queryVO.setStatus(r.getStatus());
            queryVO.setStatusCode(r.getStatusCode());
            queryVO.setOperate(r.getOperate());
            queryVO.setOperateTime(DateUtil.format(DateUtil.date(r.getOperateTime()), "yyyy-MM-dd HH:mm"));
            queryVO.setOpinion(r.getOpinion());

            return queryVO;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(result.getTotalElements(), resultList));
    }

    /**
     * 分页查询换货外部工作流
     * @author 伍将
     * @date 2020/12/11
     * @param user:
     * @param pageVO:
     * @return 换货外部工作流
     **/
    @Override
    public Wrapper<PageData<ReplaceOuterWorkflowRecordVO>> pageReplaceRecord(UserLoginCacheDTO user, WorkflowPageVO pageVO) {
        Page<OuterWorkflowRecordDO> result = pageRecord(pageVO, AfterSaleTypeEnum.REPLACE.getCode());
        AtomicReference<Integer> step = new AtomicReference<>((pageVO.getCurrent() - 1) * pageVO.getPageSize() + 1);
        List<ReplaceOuterWorkflowRecordVO> resultList = result.getContent().stream().map(r -> {
            ReplaceOuterWorkflowRecordVO queryVO = new ReplaceOuterWorkflowRecordVO();
            queryVO.setStep(step.get());
            step.getAndSet(step.get() + 1);
            queryVO.setRoleName(r.getRoleName());
            queryVO.setStatus(r.getStatus());
            queryVO.setStatusCode(r.getStatusCode());
            queryVO.setOperate(r.getOperate());
            queryVO.setOperateTime(DateUtil.format(DateUtil.date(r.getOperateTime()), "yyyy-MM-dd HH:mm"));
            queryVO.setOpinion(r.getOpinion());

            return queryVO;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(result.getTotalElements(), resultList));
    }

    /**
     * 分页查询退货外部工作流
     * @author 伍将
     * @date 2020/12/11
     * @param user:
     * @param pageVO:
     * @return 退货外部工作流
     **/
    @Override
    public Wrapper<PageData<ReturnOuterWorkflowRecordVO>> pageReturnRecord(UserLoginCacheDTO user, WorkflowPageVO pageVO) {
        Page<OuterWorkflowRecordDO> result = pageRecord(pageVO, AfterSaleTypeEnum.RETURN.getCode());
        AtomicReference<Integer> step = new AtomicReference<>((pageVO.getCurrent() - 1) * pageVO.getPageSize() + 1);
        List<ReturnOuterWorkflowRecordVO> resultList = result.getContent().stream().map(r -> {
            ReturnOuterWorkflowRecordVO queryVO = new ReturnOuterWorkflowRecordVO();
            queryVO.setStep(step.get());
            step.getAndSet(step.get() + 1);
            queryVO.setRoleName(r.getRoleName());
            queryVO.setStatus(r.getStatus());
            queryVO.setStatusCode(r.getStatusCode());
            queryVO.setOperate(r.getOperate());
            queryVO.setOperateTime(DateUtil.format(DateUtil.date(r.getOperateTime()), "yyyy-MM-dd HH:mm"));
            queryVO.setOpinion(r.getOpinion());

            return queryVO;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(result.getTotalElements(), resultList));
    }

    /**
     * 分页查询记录
     * @author 伍将
     * @date 2020/12/11
     * @param pageVO:
     * @param applyType:
     * @return 查询记录
     **/
    private Page<OuterWorkflowRecordDO> pageRecord(WorkflowPageVO pageVO, Integer applyType) {
        // step 1: 组装查询条件
        Specification<OuterWorkflowRecordDO> spec = (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.equal(root.get("afterSaleId").as(Long.class), pageVO.getDataId()));
            list.add(criteriaBuilder.equal(root.get("afterSaleType").as(Integer.class), applyType));


            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        // step 2: 组装分页参数
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("operateTime").ascending());

        return outerRecordRepository.findAll(spec, page);
    }


    public PageData<OperateLogOuterResponDto> pageReturnOuterRecordCommon(UserLoginCacheDTO loginUser, OperateLogInputDto pageVO){
        // 查询表实体
        QReturnGoodsDO returnGoodsDO=QReturnGoodsDO.returnGoodsDO;
        QOuterWorkflowRecordDO outerWorkflowRecordDO=QOuterWorkflowRecordDO.outerWorkflowRecordDO;
        // 查询条件构造
        BooleanBuilder predicates = new BooleanBuilder();
        predicates.and(outerWorkflowRecordDO.afterSaleType.eq(pageVO.getAfterSaleType()));
        //申请单号
        if(StringUtils.hasLength(pageVO.getApplyNo())){
            predicates.and(returnGoodsDO.applyNo.eq(pageVO.getApplyNo()));
        }
        //时间
        if(pageVO.getStartTime()!=null){
            predicates.and(outerWorkflowRecordDO.operateTime.goe(pageVO.getStartTime()));
        }
        if(pageVO.getEndTime()!=null){
            predicates.and(outerWorkflowRecordDO.operateTime.loe(pageVO.getEndTime()));
        }
        //会员id
        if(loginUser!=null){
            predicates.and(outerWorkflowRecordDO.memberId.eq(loginUser.getMemberId()));
            predicates.and(outerWorkflowRecordDO.roleId.eq(loginUser.getMemberRoleId()));
        }
        // 关联查询
        JPAQuery<OperateLogOuterResponDto> query = jpaQueryFactory
                .select(Projections.bean(OperateLogOuterResponDto.class,
                        returnGoodsDO.applyNo,
                        outerWorkflowRecordDO.afterSaleType,
                        outerWorkflowRecordDO.roleName,
                        outerWorkflowRecordDO.status,
                        outerWorkflowRecordDO.operate,
                        outerWorkflowRecordDO.operateTime,
                        outerWorkflowRecordDO.opinion)
                )
                .from(returnGoodsDO)
                .innerJoin(outerWorkflowRecordDO)
                .on(returnGoodsDO.id.eq(outerWorkflowRecordDO.afterSaleId))
                .where(predicates);

        long totalCount = query.fetchCount();
        List<OperateLogOuterResponDto> responses = query.orderBy(outerWorkflowRecordDO.operateTime.desc())
                .offset(pageVO.getCurrentOffset())
                .limit(pageVO.getPageSize())
                .fetch();
        return new PageData<>(totalCount, responses);
    }

    public PageData<OperateLogOuterResponDto> pageReplaceOuterRecordCommon(UserLoginCacheDTO loginUser, OperateLogInputDto pageVO){
        // 查询表实体
        QReplaceGoodsDO replaceGoodsDO=QReplaceGoodsDO.replaceGoodsDO;
        QOuterWorkflowRecordDO outerWorkflowRecordDO=QOuterWorkflowRecordDO.outerWorkflowRecordDO;
        // 查询条件构造
        BooleanBuilder predicates = new BooleanBuilder();
        predicates.and(outerWorkflowRecordDO.afterSaleType.eq(pageVO.getAfterSaleType()));
        //申请单号
        if(StringUtils.hasLength(pageVO.getApplyNo())){
            predicates.and(replaceGoodsDO.applyNo.eq(pageVO.getApplyNo()));
        }
        //时间
        if(pageVO.getStartTime()!=null){
            predicates.and(outerWorkflowRecordDO.operateTime.goe(pageVO.getStartTime()));
        }
        if(pageVO.getEndTime()!=null){
            predicates.and(outerWorkflowRecordDO.operateTime.loe(pageVO.getEndTime()));
        }
        //会员id
        if(loginUser!=null){
            predicates.and(outerWorkflowRecordDO.memberId.eq(loginUser.getMemberId()));
            predicates.and(outerWorkflowRecordDO.roleId.eq(loginUser.getMemberRoleId()));
        }
        // 关联查询
        JPAQuery<OperateLogOuterResponDto> query = jpaQueryFactory
                .select(Projections.bean(OperateLogOuterResponDto.class,
                        replaceGoodsDO.applyNo,
                        outerWorkflowRecordDO.afterSaleType,
                        outerWorkflowRecordDO.roleName,
                        outerWorkflowRecordDO.status,
                        outerWorkflowRecordDO.operate,
                        outerWorkflowRecordDO.operateTime,
                        outerWorkflowRecordDO.opinion)
                )
                .from(replaceGoodsDO)
                .innerJoin(outerWorkflowRecordDO)
                .on(replaceGoodsDO.id.eq(outerWorkflowRecordDO.afterSaleId))
                .where(predicates);

        long totalCount = query.fetchCount();
        List<OperateLogOuterResponDto> responses = query.orderBy(outerWorkflowRecordDO.operateTime.desc())
                .offset(pageVO.getCurrentOffset())
                .limit(pageVO.getPageSize())
                .fetch();
        return new PageData<>(totalCount, responses);
    }

    public PageData<OperateLogOuterResponDto> pageRepairOuterRecordCommon(UserLoginCacheDTO loginUser, OperateLogInputDto pageVO){
        // 查询表实体
        QRepairGoodsDO repairGoodsDO=QRepairGoodsDO.repairGoodsDO;
        QOuterWorkflowRecordDO outerWorkflowRecordDO=QOuterWorkflowRecordDO.outerWorkflowRecordDO;
        // 查询条件构造
        BooleanBuilder predicates = new BooleanBuilder();
        predicates.and(outerWorkflowRecordDO.afterSaleType.eq(pageVO.getAfterSaleType()));
        //申请单号
        if(StringUtils.hasLength(pageVO.getApplyNo())){
            predicates.and(repairGoodsDO.applyNo.eq(pageVO.getApplyNo()));
        }
        //时间
        if(pageVO.getStartTime()!=null){
            predicates.and(outerWorkflowRecordDO.operateTime.goe(pageVO.getStartTime()));
        }
        if(pageVO.getEndTime()!=null){
            predicates.and(outerWorkflowRecordDO.operateTime.loe(pageVO.getEndTime()));
        }
        //会员id
        if(loginUser!=null){
            predicates.and(outerWorkflowRecordDO.memberId.eq(loginUser.getMemberId()));
            predicates.and(outerWorkflowRecordDO.roleId.eq(loginUser.getMemberRoleId()));
        }
        // 关联查询
        JPAQuery<OperateLogOuterResponDto> query = jpaQueryFactory
                .select(Projections.bean(OperateLogOuterResponDto.class,
                        repairGoodsDO.applyNo,
                        outerWorkflowRecordDO.afterSaleType,
                        outerWorkflowRecordDO.roleName,
                        outerWorkflowRecordDO.status,
                        outerWorkflowRecordDO.operate,
                        outerWorkflowRecordDO.operateTime,
                        outerWorkflowRecordDO.opinion)
                )
                .from(repairGoodsDO)
                .innerJoin(outerWorkflowRecordDO)
                .on(repairGoodsDO.id.eq(outerWorkflowRecordDO.afterSaleId))
                .where(predicates);

        long totalCount = query.fetchCount();
        List<OperateLogOuterResponDto> responses = query.orderBy(outerWorkflowRecordDO.operateTime.desc())
                .offset(pageVO.getCurrentOffset())
                .limit(pageVO.getPageSize())
                .fetch();
        return new PageData<>(totalCount, responses);
    }


}
